package com.xusheng.cli.tools;

import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.xusheng.cli.common.base.Attachment;
import com.xusheng.cli.common.enums.FileDirectoryEnum;
import com.xusheng.cli.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author 痴
 * @since 2020-11-22 12:43
 */
@Slf4j
@Component
public class FileUtils {

    private static String FILE_DIRECTORY_PATH;

    @Value("${upload.path}")
    private String fileDirectoryPathBean;


    @PostConstruct
    public void init() {
        FILE_DIRECTORY_PATH = fileDirectoryPathBean;
    }

    public static Dict generateFilePath(FileDirectoryEnum fileDirectoryEnum, String suffixName) {
        String newName = IdUtil.simpleUUID() + "." + suffixName;
        String directory = fileDirectoryEnum.getDirectory();
        String staticPath = directory + File.separator + newName;
        return Dict.create().set("url", "/static_data" + File.separator + staticPath).set("path", FILE_DIRECTORY_PATH + staticPath);
    }

    /**
     * 上传单个文件
     *
     * @param file 上传的文件
     * @param path 文件存放模块
     * @return com.jieao.template.common.util.Attachment 存放文件信息
     * @author 痴
     * @since 2020/11/22 13:29
     */
    public static Attachment uploadSingleFile(MultipartFile file, String path) {
        log.info("上传开始");
        String originalFileName = file.getOriginalFilename();
        // 获取文件的后缀名
        assert originalFileName != null;
        String suffixName = originalFileName.substring(originalFileName.lastIndexOf(".") + 1);

        // 文件的新名字
        String newName = IdUtil.simpleUUID() + "." + suffixName;
        String staticPath = path + File.separator + newName;
        // 设置文件存储路径
        String filePath = FILE_DIRECTORY_PATH + staticPath;
        File dest = new File(filePath);
        // 检测是否存在目录
        if (!dest.getParentFile().exists()) {
            // 新建文件夹
            boolean mkdir = dest.getParentFile().mkdirs();
            if (!mkdir) {
                throw new ServiceException("创建目录失败");
            }
        }
        //保存在本地
        try {
            log.info("上传中");
            file.transferTo(dest);
//            Files.write(Paths.get(filePath), file.getBytes());
            // 设置目标文件的公共读取权限（例如：所有用户都可以读取）
/*            Set<PosixFilePermission> permissions = new HashSet<>();
            permissions.add(PosixFilePermission.OWNER_READ);
            permissions.add(PosixFilePermission.GROUP_READ);
            permissions.add(PosixFilePermission.OTHERS_READ);
            Files.setPosixFilePermissions(Paths.get(filePath), permissions);*/
        } catch (IOException e) {
            log.info(e.getLocalizedMessage());
            throw new ServiceException("上传文件失败!");
        }
        Attachment attachment = new Attachment();
        attachment.setPath(filePath);
        attachment.setUrl("/static_data" + File.separator + staticPath);
        attachment.setMd5(DigestUtil.md5Hex(dest));
        attachment.setOriginalName(originalFileName);
        attachment.setNewName(newName);
        attachment.setSuffixName(suffixName);
        log.info("上传结束");
        return attachment;
    }

    /**
     * 上传单个文件
     *
     * @param file              上传的文件
     * @param fileDirectoryEnum 文件存放模块
     * @return com.jieao.template.common.util.Attachment 存放文件信息
     * @author 痴
     * @since 2020/11/22 13:29
     */
    public static Attachment uploadSingleFile(MultipartFile file, FileDirectoryEnum fileDirectoryEnum) {
        return uploadSingleFile(file, fileDirectoryEnum.getDirectory());
    }

    /**
     * 上传多个文件
     *
     * @param files             上传多个文件
     * @param fileDirectoryEnum 文件存放模块
     * @return java.util.List<com.jieao.template.common.util.Attachment> 存放文件信息
     * @author 痴
     * @since 2020/11/22 13:29
     */
    public static List<Attachment> uploadMultipleFile(MultipartFile[] files, FileDirectoryEnum fileDirectoryEnum) {
        if (files.length > 0 && !(files[0].isEmpty())) {
            List<Attachment> attachments = new ArrayList<>(files.length);
            for (MultipartFile file : files) {
                attachments.add(uploadSingleFile(file, fileDirectoryEnum));
            }
            return attachments;
        } else {
            throw new ServiceException("请上传文件");
        }

    }

    /**
     * 上传富文本图片
     *
     * @param file 富文本图片
     * @return com.jieao.template.common.util.Attachment 存放文件信息
     * @author 痴
     * @since 2020/11/22 13:34
     */
    public static Attachment uploadRichTextImage(MultipartFile file) {
        return uploadSingleFile(file, FileDirectoryEnum.RICHTEXTIMAGE);
    }

    /**
     * 文件下载/回显图片
     *
     * @param filePath     文件全路径 例如 /usr/upload/65654654.jpg
     * @param originalName 文件原名 用于下载时显示的文件名
     * @return org.springframework.http.ResponseEntity<byte [ ]>
     * @author 痴
     * @since 2020/11/22 14:13
     */
    public static ResponseEntity<byte[]> downloadFileByFullName(String filePath, String originalName) {
        //读取流
        try {
            byte[] body = Files.readAllBytes(Paths.get(filePath));
            HttpHeaders httpHeaders = new HttpHeaders();
            //设置文件类型
            httpHeaders.add("Content-Disposition", "attachment;filename=" + new String(originalName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
            // 设置Http状态码
            HttpStatus statusCode = HttpStatus.OK;
            // 返回数据
            return new ResponseEntity<>(body, httpHeaders, statusCode);
        } catch (IOException e) {
            throw new ServiceException("文件不存在!");
        }

    }

    /**
     * 文件下载/回显图片
     *
     * @param fileName     文件名 例如 65654654.jpg
     * @param originalName 文件原名 用于下载时显示的文件名
     * @return org.springframework.http.ResponseEntity<byte [ ]>
     * @author 痴
     * @since 2020/11/22 14:13
     */
    public static ResponseEntity<byte[]> downloadFileByFileName(String fileName, FileDirectoryEnum fileDirectoryEnum, String originalName) {
        //读取流
        try {
            byte[] body = Files.readAllBytes(Paths.get(FILE_DIRECTORY_PATH + fileDirectoryEnum.getDirectory(), fileName));
            HttpHeaders httpHeaders = new HttpHeaders();
            //设置文件类型
            httpHeaders.add("Content-Disposition", "attachment;filename=" + new String(originalName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
            // 设置Http状态码
            HttpStatus statusCode = HttpStatus.OK;
            // 返回数据
            return new ResponseEntity<>(body, httpHeaders, statusCode);
        } catch (IOException e) {
            throw new ServiceException("文件不存在!");
        }

    }

    public static boolean isImage(String originalFilename) {
        if (originalFilename == null)
            return false;
        if (originalFilename.contains(".")) {
            String fileExt = originalFilename.substring(originalFilename.lastIndexOf("."));
            fileExt = fileExt.toLowerCase();
            return fileExt.equals(".jpg")
                    || fileExt.equals(".jpeg")
                    || fileExt.equals(".gif")
                    || fileExt.equals(".png")
                    || fileExt.equals(".bmp");
        }
        return false;
    }
}
